/*!
 * \file ColorBranching.h
 *
 * \date Jul 30, 2014
 * \author correa
 */
#ifndef COLORBRANCHING_H_
#define COLORBRANCHING_H_

#include <Desigualdad.h>
#include <StabBranching.h>
#include <list>
#include <cstdlib>

using namespace std;

template <class T>
class RepBranching : public StabBranching, public FactoryDesigualdadArray<T>
{
//	VertexSet					_dominados;
	VertexSet					_vecinos;
	VertexSet					_novecinos;
	list<DesigualdadArray<T> *>	_desigualdades;

protected:
	virtual DesigualdadArray<T> * newDesigualdadArray() = 0;
	virtual DesigualdadArray<T> * newDesigualdadArray(const DesigualdadArray<T>& otra) = 0;

public:
	RepBranching(Grafo& g, ReservaClique * reserva=NULL);
	virtual ~RepBranching();
	list<DesigualdadArray<T> *>& branchEqual(int u, int v);
	list<DesigualdadArray<T> *>& branchDiffer(int u, int v);
};

template <class T>
inline RepBranching<T>::RepBranching(Grafo& g, ReservaClique * reserva) : StabBranching(g, reserva),
_vecinos(g.getN()), _novecinos(g.getN()), _desigualdades() // , _dominados(grafo.getN())
{
}

template <class T>
inline RepBranching<T>::~RepBranching()
{
}

template <class T>
inline list<DesigualdadArray<T> *>& RepBranching<T>::branchEqual(int u, int v) {
	_desigualdades.clear();

	DesigualdadArray<T> * ret = newDesigualdadArray();
	(*ret)[u].setCoeficiente(u, 1);
	(*ret)[u].setCoeficiente(v, 1);
	ret->setRHS(1);
	_desigualdades.push_back(ret);

	ret = newDesigualdadArray();
	(*ret)[u].setCoeficiente(u, -1);
	(*ret)[u].setCoeficiente(v, -1);
	ret->setRHS(-1);
	_desigualdades.push_back(ret);

	_novecinos.copyCompl(_grafo.vecinos(v));
	_novecinos.remove(u);
	for (VertexSetIterator r = _novecinos.begin(u); *r < v; ++r) {
		ret = newDesigualdadArray();
		(*ret)[u].setCoeficiente(v, 1);
		(*ret)[*r].setCoeficiente(*r, -1);
		_vecinos.copyAll(_grafo.vecinos(v));
		_vecinos.removeAll(_grafo.vecinos(*r));
		for (VertexSetIterator w = _vecinos.begin(*r); w != _vecinos.end(); ++w)
			(*ret)[*r].setCoeficiente(*w, -1);
		ret->setRHS(0);
		_desigualdades.push_back(ret);
	}

	return _desigualdades;
}

template <class T>
inline list<DesigualdadArray<T> *>& RepBranching<T>::branchDiffer(int u, int v) {
	_desigualdades.clear();

	DesigualdadArray<T> * ret = newDesigualdadArray();
	(*ret)[u].setCoeficiente(u, 1);
	ret->setRHS(0);
	_desigualdades.push_back(ret);

	ret = newDesigualdadArray();
	(*ret)[u].setCoeficiente(v, 1);
	ret->setRHS(0);
	_desigualdades.push_back(ret);

	return _desigualdades;
}

#endif /* COLORBRANCHING_H_ */
